#include "DbServer.h"
#include "svr_util/include/read_cfg.h"
#include "db_con.h"

using namespace std;
using namespace lc;
using namespace proto;
using namespace su;
using namespace proto;



#undef RpcReg
#define RpcReg(fun) STATIC_RUN( RpcNetSvr<ConToClient>::Ins().RegFun(fun, #fun);) 


namespace
{
	bool Insert(const string& data)
	{
		std::unique_ptr<BaseTable> pTable = TableCfg::Ins().Unpack(data);
		L_COND_F(nullptr != pTable);
		bool ret = DbConMgr::Ins().GetCon().Insert(*pTable);
		return ret;
	}
	RpcReg(Insert);

	bool Del(uint16_t table_id, const std::string& cond)
	{
		return DbConMgr::Ins().GetCon().Del(table_id, cond);
	}
	RpcReg(Del);

	//@table_id  BaseTable::TableId()
	//@cond 条件，sql语法
	//@限制数量 0 表示不限制
	//@RetRpcFun 注册返回给client的rpc函数.  void(const std::string& data) data.empty() 表示最后一次返回。
	void QueryCondForMore(uint16_t table_id, const std::string& cond, uint32_t limitNum)
	{
		L_DEBUG("query by cond string, table_id= %d", table_id);
		ConToClient* pCon = RpcNetSvr<ConToClient>::Ins().GetCurCon();
		L_COND_V(pCon);
		QueryResultRowCb cb = [table_id, &pCon](const proto::BaseTable& retData)//pCon引用是安全的
		{
			string str;
			L_COND_V(TableCfg::Ins().Pack(retData, str));			RpcNetSvr<ConToClient>::Ins().CallNoRet(*pCon, "RevQueryCondForMore", table_id, str);
		};
		DbConMgr::Ins().GetCon().Query(table_id, cond, limitNum, cb);		RpcNetSvr<ConToClient>::Ins().CallNoRet(*pCon, "RevQueryCondForMore", table_id, string());
	}
	RpcReg(QueryCondForMore);

	//查找失败，返回空字符
	string QueryCond(uint16_t table_id, const std::string& cond)
	{
		string str;
		L_DEBUG("QueryCond by cond string, table_id= %d", table_id);
		QueryResultRowCb cb = [&str](const proto::BaseTable& retData)//pCon引用是安全的
		{
			L_COND_V(TableCfg::Ins().Pack(retData, str));		};
		DbConMgr::Ins().GetCon().Query(table_id, cond, 1, cb);
		return str;
	}
	RpcReg(QueryCond);

	//查询部分字段
	//查找失败，返回空字符
	string QueryCondPartly(uint16_t table_id, const std::string& cond, const std::vector<std::string>& vecFieldName)
	{
		string str;
		vector<int> vecIdx;
		const Table *table = TableCfg::Ins().GetTable(table_id);
		L_COND(table, str);
		for (auto &name : vecFieldName)
		{
			const Field* field = table->GetField(name);
			L_COND(field, str, "can't find field name %s", name.c_str());
			vecIdx.push_back(field->idx);
		}
		L_DEBUG("QueryCond by cond string, table_id= %d", table_id);
		QueryResultRowCb cb = [&str, &vecIdx](const proto::BaseTable& retData)
		{
			L_COND_V(TableCfg::Ins().Pack(retData, str, &vecIdx));		};
		DbConMgr::Ins().GetCon().Query(table_id, cond, vecFieldName, cb);
		return str;
	}
	RpcReg(QueryCondPartly);

	void Update(const string& data)
	{
		std::unique_ptr<BaseTable> pTable = TableCfg::Ins().Unpack(data);
		L_COND_V(nullptr != pTable);
		DbConMgr::Ins().GetCon().Update(*pTable);
	}
	RpcReg(Update);


	bool Sql(const string& sql)
	{
		return DbConMgr::Ins().GetCon().ExecuteSql(sql);
	}
	RpcReg(Sql);
}
